﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetDon.OA.Data.CollectionClasses;
using NetDon.OA.Data.EntityClasses;
using NetDon.OA.Data.HelperClasses;
using NetDon.OA.Data.Linq;
using NetDon.OA.Interface.Admin;
using SD.LLBLGen.Pro.ORMSupportClasses;
using Expression = System.Linq.Expressions.Expression;

namespace NetDon.OA.Business.Admin
{
    public class CompanyService : PrimitiveHierarchyService<CompanyData>, ICompanyService
    {
        public CompanyService()
            : base("CompanyData")
        {
        }
        #region ICompanyService Members
        public CompanyDataCollection GetChildCompanies(Guid companyId)
        {
            return new CompanyDataCollection(GetChildNodes(companyId).OrderBy(i => i.CompanyName).ToArray());
        }

        public CompanyDataCollection GetRootCompanies()
        {
            return new CompanyDataCollection(GetRootNodes().OrderBy(i => i.CompanyName).ToArray());
        }

        public CompanyData GetCompany(Guid companyId)
        {
            return GetData(companyId);
        }

        public bool RemoveCompany(Guid companyId)
        {
            return RemoveData(companyId);
        }

        public bool CheckCompanyUsed(Guid companyId)
        {
            var company = GetCompany(companyId);
            if (company == null)
            {
                return false;
            }

           return new CompanyCollection().GetDbCount(CompanyFields.ParentCompanyId == companyId)>0 ||
          
                new DepartmentCollection().GetDbCount(DepartmentFields.CompanyId ==companyId) >0;
        }

        public bool AddCompany(CompanyData companyData)
        {
            return AddData(companyData);
        }

        public bool ModifyCompany(CompanyData companyData)
        {
            return ModifyData(companyData.CompanyId, companyData);
        }
        #endregion


        #region Overrides of CachableServiceBase<CompanyData>

        protected override CompanyData OnLoadData(object key, ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            List<CompanyEntity> list = (from company in meta.Company
                                        where company.CompanyId == (Guid)key
                                        select company).ToList();
            return list.Count > 0 ? GetCompanyData(list[0]) : null;
        }

        protected override object GetDataKey(CompanyData data)
        {
            return data.CompanyId;
        }

        protected override bool OnRemoveData(object key, CompanyData data, ITransaction transaction)
        {
            if (base.OnRemoveData(key, data, transaction))
            {
                var collection = new Data.CollectionClasses.CompanyCollection();
                transaction.Add(collection);
                return collection.DeleteMulti(CompanyFields.CompanyId == (Guid)key) > 0;
            }
            return false;
        }

        protected override bool OnAddData(CompanyData data, ITransaction transaction)
        {
            if (!ValidateCompany(data, transaction))
            {
                return false;
            }
            string parentPath = data.ParentId.HasValue ? GetCompany(data.ParentId.Value).Path : string.Empty;
            var childNodes = data.ParentId.HasValue ? GetChildNodes(data.ParentId.Value) : GetRootNodes();
            string path = parentPath + childNodes.Count().ToString("X").PadLeft(4, '0');
            var entity = new CompanyEntity
            {

                ParentCompanyId = data.ParentId,
                CompanyCode = data.CompanyCode,
                CompanyName = data.CompanyName,
                Address = data.Address,
                CompanyDesc = data.CompanyDesc,
                CompanyId = data.CompanyId,
                Email = data.Email,
                Fax = data.Fax,
                Website = data.Website,
                PostCode = data.PostCode,
                Telephone = data.Telephone,
                NodeLevel = data.NodeLevel,
                Ceo =data.CEO,
                Ceoassistant =data.CEOAssistant
            };
            transaction.Add(entity);
            if (entity.Save())
            {
                data.CompanyId = entity.CompanyId;
                data.Path = path;
                return true;
            }
            return false;
        }

        protected override bool OnModifyData(object key, CompanyData data, ITransaction transaction)
        {
            if (!ValidateCompany(data, transaction))
            {
                return false;
            }
            var entity = new CompanyEntity();
            transaction.Add(entity);
            entity.FetchUsingPK((Guid)key);
            if (entity.IsNew)
            {
                return false;
            }
            var path = GetCompany((Guid)key).Path;
            entity.ParentCompanyId = data.ParentId;
            entity.CompanyCode = data.CompanyCode;
            entity.CompanyName = data.CompanyName;
            entity.Address = data.Address;
            entity.CompanyDesc = data.CompanyDesc;
            entity.CompanyId = data.CompanyId;
            entity.Email = data.Email;
            entity.Fax = data.Fax;
            entity.Website = data.Website;
            entity.PostCode = data.PostCode;
            entity.Telephone = data.Telephone;
            entity.NodeLevel = data.NodeLevel;
            entity.Ceo = data.CEO;
            entity.Ceoassistant = data.CEOAssistant;
            return entity.Save();
        }

        #endregion

        #region Overrides of HierarchyCachableService<CompanyData>

        protected override object GetParentKey(CompanyData data)
        {
            return data.ParentId;
        }

        protected override IEnumerable<CompanyData> OnLoadChildNodes(object parentKey,
                                                                               ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from company in meta.Company
                        where company.ParentCompanyId == (Guid?)parentKey
                        select company).ToList();
            return list.Select(company => GetCompanyData(company));
        }

        #endregion

        #region Overrides of PrimitiveHierarchyService<CompanyData>

        protected override IEnumerable<CompanyData> OnLoadRootNodes(ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from company in meta.Company
                        where company.ParentCompanyId == null
                        select company).ToList();
            return list.Select(category => GetCompanyData(category));
        }

        #endregion

        private static CompanyData GetCompanyData(CompanyEntity entity)
        {
            return new CompanyData
            {
                ParentId = entity.ParentCompanyId,
                CompanyCode = entity.CompanyCode,
                CompanyName = entity.CompanyName,
                Address = entity.Address,
                CompanyDesc = entity.CompanyDesc,
                CompanyId = entity.CompanyId,
                Email = entity.Email,
                Fax = entity.Fax,
                Website = entity.Website,
                PostCode = entity.PostCode,
                Telephone = entity.Telephone,
                NodeLevel =entity.NodeLevel

            };
        }
        private bool ValidateCompany(CompanyData data, ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from company in meta.Company
                        where company.CompanyCode == data.CompanyCode && company.CompanyId != data.CompanyId
                        select company).ToList();
            if (list.Count > 0)
            {
                data.SetError("CompanyCode",
                             string.Format("The company code '{0}' has existed.", data.CompanyCode));
                return false;
            }

            list = (from company in meta.Company
                    where company.CompanyName == data.CompanyName && company.CompanyId != data.CompanyId
                    select company).ToList();
            if (list.Count > 0)
            {
                data.SetError("CompanyName",
                             string.Format("The company '{0}' has existed.", data.CompanyName));
                return false;
            }
            //CompanyDataCollection companies = data.ParentId.HasValue
            //                                             ? GetChildCompanies(data.ParentId.Value)
            //                                             : GetRootCompanies();
            //if (companies != null &&
            //    companies.ToList().Find(
            //        company =>
            //        String.Compare(company.CompanyName, data.CompanyName, true) == 0 &&
            //        company.CompanyId != data.CompanyId) !=
            //    null)
            //{
            //    data.SetError("CompanyName",
            //                  string.Format("The company '{0}' has existed.", data.CompanyName));
            //    return false;
            //}
            return true;
        }
    }
}
